import { ES3DTileset, reactJson, reactJsonWithUndefined, UniteChanged } from "earthsdk3";
import { ESRtsTileset2 } from "../ESRtsTileset2";
/**
 * 检查一个值是否为有效的数字。
 * @param value - 要检查的值。
 * @returns 如果值是有效的数字，则返回 true；否则返回 false。
 */
function isNumber(value: any): boolean {
    return typeof value === 'number' && !isNaN(value);
}

/**
 * ESRtsFeatureEditing2 类继承自 ES3DTileset，用于实时3DTileset图层的要素编辑。
 * 该类提供了初始化要素编辑、设置要素属性、获取和设置JSON表示等功能。
 * 
 * 核心功能包括：
 * - 初始化要素编辑（init方法）
 * - 获取和设置对象的JSON表示（get json 和 set json）
 * - 设置要素编辑的相关属性
 * 
 * 使用示例：
 * 
 * 构造函数参数：
 * - id: 场景对象的键，可选参数。
 * 
 * 特殊使用限制或潜在的副作用：
 * - 在初始化时，需要传入有效的 ESRtsTileset2 对象和 featureId。
 * - 如果 tileServiceIp 或 tilesetServePort 未定义，会抛出错误。
 * - 该类重写了部分 ES3DTileset 的方法，可能会影响原有功能的使用。
 */
export class ESRtsFeatureEditing2 extends ES3DTileset {
    static override readonly createDefaultProps = () => ({
        ...ES3DTileset.createDefaultProps(),
        /**数据集名称 */
        datasetName: undefined as string | undefined,
        /**feature Id */
        featureId: undefined as string | undefined,
        /**材质 */
        materials: reactJson<any>({}),
        /**材质变化存储 */
        changeMaterial: reactJsonWithUndefined<{ oldMaterialId: string, newMaterialId: string }>(undefined),
        /**ui是否显示属性 */
        uiShowprops: reactJson<any>({}),

        /**属性对象 */
        props: reactJson<any>({}),
    });
    /**
     * 静态属性，用于注册类的类型信息。
     */
    static override readonly type: string = this.register('ESRtsFeatureEditing2', this, { chsName: 'ESRtsFeatureEditing2', tags: ['ESObjects', '_ES_Impl_Cesium', '_ES_Impl_UE'], description: "实时3DTileset图层" });
    /**
     * 重写的方法，获取对象的 JSON 表示。
     * @returns 包含对象属性的 JSON 值。
     */
    override get json() {
        return {
            // @ts-ignore
            ...this._innerGetJson(),
            "show": this.show,
            "materials": this.materials,
            "changeMaterial": this.changeMaterial,
            "props": this.props,
            "rotation": this.rotation,
            "offset": this.offset
        } as JsonValue;
    }

    /**
     * 重写的方法，设置对象的 JSON 表示。
     * @param value - 要设置的 JSON 值。
     */
    override set json(value: JsonValue) { this._innerSetJson(value); }

    /**
     * 初始化方法，用于设置要素编辑的相关属性。
     * @param eSRtsTileset - 关联的 ESRtsTileset2 对象。
     * @param featureId - 要素的 ID。
     */
    async init(eSRtsTileset: ESRtsTileset2, featureId: string) {
        this.featureId = featureId;
        const uiShowprops = await eSRtsTileset.getFeatureProperty(featureId) as any;
        this.uiShowprops = uiShowprops.allFields.map((e: any) => {
            return {
                featureClassName: e.featureClassName,
                fields: e.fields.map((f: any) => {
                    return {
                        key: f.name,
                        type: f.type,
                        value: f.type != "Double" ? f.value : (isNumber(f.value) ? Number(f.value.toFixed(3)) : "")
                    }
                })
            }
        })
        this.datasetName = uiShowprops.datasetName

        // 隐藏原来大的中的 feature
        eSRtsTileset.setFeatureVisable('id', [{ value: this.featureId, visable: false }]);
        this.d(() => { eSRtsTileset.setFeatureVisable('id', [{ value: this.featureId, visable: true }]) });

        if (!eSRtsTileset.isSameIP) {
            const ip = eSRtsTileset.tileServiceIp; // http://localhost
            const port = eSRtsTileset.tilesetServePort; // 9014
            if (!port) {
                throw new Error('ESRtsFeatureEditing2: port is not defined');
            }
            this.url = `${ip}:${port}/featuretiles/${this.featureId}/tileset.json`;

        } else {
            // @ts-ignore
            const ipPort = eSRtsTileset.url.match(/^(https?:\/\/[^\/]+)/)?.[0]
            const tileServiceName = eSRtsTileset.tileServiceName; // test
            this.url = `${ipPort}/ts/featuretiles/${tileServiceName}/${this.featureId}/tileset.json`;
        }
        this.allowPicking = true;

        // 将 ES3DTileset 的 pickedEvent 事件绑定到 ESDSFeature 的 pickedEvent 事件上
        this.d(this.pickedEvent.don((pickedInfo) => {
            pickedInfo.assign({ sceneObject: eSRtsTileset })
            // @ts-ignore
            eSRtsTileset.pickedEvent.emit(pickedInfo);
        }))

        this.d(() => {
            this.editing = false;
            eSRtsTileset.removeHighlightDSFeature(this)
        })
    }

    /**
     * 构造函数，初始化 ESRtsFeatureEditing2 实例。
     * @param id - 场景对象的键，可选参数。
     */
    constructor(id?: string) {
        super(id);
    }
}
/**
 * ESRtsFeatureEditing2 接口，继承自 UniteChanged，用于类型定义。
 */
export interface ESRtsFeatureEditing2 extends UniteChanged<ReturnType<typeof ESRtsFeatureEditing2.createDefaultProps>> { }
